#!/usr/bin/env python3
"""
RedFire Backend 统一入口脚本
===========================

提供多种启动模式:
1. 启动所有微服务 (开发模式)
2. 启动指定微服务
3. 健康检查
4. 服务管理
"""

import os
import sys
import time
import signal
import argparse
import subprocess
import threading
from pathlib import Path
from typing import List, Dict, Optional
import requests
import json


class RedFireBackendManager:
    """RedFire Backend 管理器"""
    
    def __init__(self):
        self.project_root = Path(__file__).parent
        self.services = {
            'api_gateway': {
                'port': 8000,
                'path': 'services/api_gateway/app/main.py',
                'description': 'API网关服务'
            },
            'user_service': {
                'port': 8002,
                'path': 'services/user_service/app/main.py',
                'description': '用户服务'
            },
            'trading_service': {
                'port': 8003,
                'path': 'services/trading_service/app/main.py',
                'description': '交易服务'
            },
            'market_data_service': {
                'port': 8004,
                'path': 'services/market_data_service/app/main.py',
                'description': '市场数据服务'
            },
            'notification_service': {
                'port': 8006,
                'path': 'services/notification_service/app/main.py',
                'description': '通知服务'
            },
            'monitoring_service': {
                'port': 8007,
                'path': 'services/monitoring_service/app/main.py',
                'description': '监控服务'
            }
        }
        self.processes: Dict[str, subprocess.Popen] = {}
        self.running = True
    
    def print_banner(self):
        """打印启动横幅"""
        banner = """
╔══════════════════════════════════════════════════════════════╗
║                     🔥 RedFire Backend 🔥                    ║
║                   量化交易平台微服务架构                        ║
╚══════════════════════════════════════════════════════════════╝
        """
        print(banner)
    
    def check_service_file(self, service_name: str) -> bool:
        """检查服务文件是否存在"""
        service_path = self.project_root / self.services[service_name]['path']
        return service_path.exists()
    
    def start_service(self, service_name: str) -> Optional[subprocess.Popen]:
        """启动单个服务"""
        if service_name not in self.services:
            print(f"❌ 未知服务: {service_name}")
            return None
        
        if not self.check_service_file(service_name):
            print(f"❌ 服务文件不存在: {service_name}")
            return None
        
        service_info = self.services[service_name]
        service_path = self.project_root / service_info['path']
        
        print(f"🚀 启动 {service_info['description']} (端口: {service_info['port']})")
        
        try:
            # 设置环境变量
            env = os.environ.copy()
            env['PYTHONPATH'] = str(self.project_root)
            
            # 启动服务进程
            process = subprocess.Popen(
                [sys.executable, str(service_path)],
                cwd=self.project_root,
                env=env,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                bufsize=1,
                universal_newlines=True
            )
            
            # 简短等待，若进程已退出则视为失败
            time.sleep(0.5)
            if process.poll() is not None:
                print(f"❌ [{service_name}] 服务启动失败 (退出码: {process.returncode})")
                return None

            # 启动日志输出线程
            threading.Thread(
                target=self._log_output,
                args=(service_name, process),
                daemon=True
            ).start()
            
            self.processes[service_name] = process
            print(f"🔄 [{service_name}] 服务正在启动...")
            return process
            
        except Exception as e:
            print(f"❌ 启动服务失败 {service_name}: {e}")
            return None
    
    def _log_output(self, service_name: str, process: subprocess.Popen):
        """处理服务日志输出"""
        service_info = self.services[service_name]
        startup_completed = False
        
        def read_stream(stream, is_error=False):
            nonlocal startup_completed
            for line in iter(stream.readline, ''):
                if not line.strip():
                    continue
                
                line_content = line.strip()
                
                # 过滤掉不重要的日志信息
                if self._should_filter_log(line_content):
                    continue
                
                # 检测启动完成状态
                if self._is_startup_complete(line_content):
                    if not startup_completed:
                        print(f"✅ [{service_name}] 服务启动完成")
                        startup_completed = True
                    continue
                
                # 只显示重要的日志信息
                if self._is_important_log(line_content):
                    prefix = "❌" if is_error or "ERROR" in line_content else "ℹ️"
                    print(f"{prefix} [{service_name}] {line_content}")
        
        # 创建线程处理stdout和stderr
        stdout_thread = threading.Thread(
            target=read_stream,
            args=(process.stdout, False),
            daemon=True
        )
        stderr_thread = threading.Thread(
            target=read_stream,
            args=(process.stderr, True),
            daemon=True
        )
        
        stdout_thread.start()
        stderr_thread.start()
        
        stdout_thread.join()
        stderr_thread.join()
    
    def start_all_services(self):
        """启动所有服务"""
        print("🚀 正在启动所有微服务...")
        print()
        
        successful_starts = 0
        for service_name in self.services:
            if self.start_service(service_name):
                successful_starts += 1
            time.sleep(1.5)  # 给每个服务一些启动时间
        
        print(f"\n📈 启动结果: {successful_starts}/{len(self.services)} 个服务成功启动")
        
        if successful_starts > 0:
            # 等待服务初始化更充分
            print("⏳ 等待服务初始化完成...")
            time.sleep(3)
            
        self.print_service_status()
    
    def stop_all_services(self):
        """停止所有服务"""
        print("\n🛑 停止所有服务...")
        
        for service_name, process in self.processes.items():
            try:
                print(f"停止 {service_name}...")
                process.terminate()
                
                # 等待进程结束，最多等待5秒
                try:
                    process.wait(timeout=5)
                except subprocess.TimeoutExpired:
                    print(f"强制终止 {service_name}...")
                    process.kill()
                    process.wait()
                    
            except Exception as e:
                print(f"停止服务失败 {service_name}: {e}")
        
        self.processes.clear()
        print("✅ 所有服务已停止")
    
    def health_check(self, service_name: Optional[str] = None) -> Dict:
        """健康检查"""
        results = {}
        
        services_to_check = [service_name] if service_name else list(self.services.keys())
        
        print("🔍 执行健康检查...")
        
        for svc_name in services_to_check:
            if svc_name not in self.services:
                results[svc_name] = {"status": "unknown", "error": "服务不存在"}
                continue
            
            port = self.services[svc_name]['port']
            url = f"http://localhost:{port}/health"
            
            try:
                response = requests.get(url, timeout=5)
                if response.status_code == 200:
                    results[svc_name] = {
                        "status": "healthy",
                        "port": port,
                        "response_time": response.elapsed.total_seconds()
                    }
                    print(f"✅ {svc_name} (:{port}) - 健康")
                else:
                    results[svc_name] = {
                        "status": "unhealthy", 
                        "port": port,
                        "status_code": response.status_code
                    }
                    print(f"❌ {svc_name} (:{port}) - 不健康 (状态码: {response.status_code})")
            
            except requests.exceptions.ConnectionError:
                results[svc_name] = {"status": "offline", "port": port}
                print(f"⭕ {svc_name} (:{port}) - 离线")
            except Exception as e:
                results[svc_name] = {"status": "error", "port": port, "error": str(e)}
                print(f"❌ {svc_name} (:{port}) - 错误: {e}")
        
        return results
    
    def print_service_status(self):
        """打印服务状态"""
        print("\n📊 服务状态:")
        print("-" * 68)
        
        running_count = 0
        for service_name, service_info in self.services.items():
            port = service_info['port']
            description = service_info['description']
            
            if service_name in self.processes:
                process = self.processes[service_name]
                if process.poll() is None:
                    status = "🟢 运行中"
                    running_count += 1
                else:
                    status = "🔴 已停止"
            else:
                status = "⚪ 未启动"
            
            print(f"{status} {service_name:<22} :{port} - {description}")
        
        print("-" * 68)
        status_summary = f"总服务数: {len(self.services)} | 运行中: {running_count}"
        if running_count == len(self.services):
            status_summary += " ✅"
        elif running_count > 0:
            status_summary += " ⚠️"
        else:
            status_summary += " ❌"
        print(status_summary)
    
    def print_access_urls(self):
        """打印访问地址"""
        print("\n🌐 服务访问地址:")
        print("-" * 60)
        
        for service_name, service_info in self.services.items():
            port = service_info['port']
            description = service_info['description']
            
            print(f"📍 {description}")
            print(f"   • API: http://localhost:{port}")
            print(f"   • 文档: http://localhost:{port}/docs")
            print(f"   • 健康检查: http://localhost:{port}/health")
            print()
    
    def _should_filter_log(self, line: str) -> bool:
        """判断是否应该过滤掉这行日志"""
        # 过滤掉的日志类型
        filter_patterns = [
            "INFO:     Started server process",
            "INFO:     Waiting for application startup",
            "INFO:     Application startup complete",
            "INFO:     Uvicorn running on",
            "Running as main script",
            "Press CTRL+C to quit",
            "✓ 路由配置已加载",
            "✓ 服务注册表已加载",
            "✓ 高级网关中间件已添加",
            "✓ Redis连接成功",
            "✓ 健康检查任务将在第一次请求时"
        ]
        
        return any(pattern in line for pattern in filter_patterns)
    
    def _is_startup_complete(self, line: str) -> bool:
        """判断服务是否启动完成"""
        startup_indicators = [
            "🚀",
            "启动完成",
            "Application startup complete",
            "Uvicorn running on"
        ]
        return any(indicator in line for indicator in startup_indicators)
    
    def _is_important_log(self, line: str) -> bool:
        """判断是否为重要日志"""
        # 重要日志的关键词
        important_patterns = [
            "ERROR",
            "CRITICAL",
            "WARNING",
            "❌",
            "⚠",
            "连接失败",
            "启动失败",
            "异常",
            "Exception",
            "Traceback"
        ]
        
        return any(pattern in line for pattern in important_patterns)
    
    def signal_handler(self, signum, frame):
        """信号处理器"""
        print(f"\n收到信号 {signum}, 正在停止所有服务...")
        self.running = False
        self.stop_all_services()
        sys.exit(0)
    
    def wait_for_services(self):
        """等待服务运行"""
        try:
            # 注册信号处理器
            signal.signal(signal.SIGINT, self.signal_handler)
            signal.signal(signal.SIGTERM, self.signal_handler)
            
            print("\n按 Ctrl+C 停止所有服务")
            print("=" * 60)
            
            while self.running and self.processes:
                # 检查进程状态
                for service_name in list(self.processes.keys()):
                    process = self.processes[service_name]
                    if process.poll() is not None:
                        print(f"⚠️  服务 {service_name} 已退出 (退出码: {process.returncode})")
                        del self.processes[service_name]
                
                if not self.processes:
                    print("所有服务已停止")
                    break
                
                time.sleep(1)
                
        except KeyboardInterrupt:
            self.signal_handler(signal.SIGINT, None)


def main():
    """主函数"""
    parser = argparse.ArgumentParser(
        description="RedFire Backend 统一入口脚本",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
使用示例:
  python main.py                    # 启动所有服务
  python main.py --service user     # 启动用户服务
  python main.py --health           # 健康检查
  python main.py --status           # 查看状态
  python main.py --list             # 列出所有服务
        """
    )
    
    parser.add_argument(
        '--service', '-s',
        help='启动指定服务'
    )
    parser.add_argument(
        '--health', '-H',
        action='store_true',
        help='执行健康检查'
    )
    parser.add_argument(
        '--status', '-S',
        action='store_true',
        help='查看服务状态'
    )
    parser.add_argument(
        '--list', '-l',
        action='store_true',
        help='列出所有可用服务'
    )
    parser.add_argument(
        '--urls', '-u',
        action='store_true',
        help='显示服务访问地址'
    )
    
    args = parser.parse_args()
    
    manager = RedFireBackendManager()
    manager.print_banner()
    
    # 列出服务
    if args.list:
        print("📋 可用服务列表:")
        print("-" * 60)
        for service_name, service_info in manager.services.items():
            print(f"• {service_name:<20} :{service_info['port']} - {service_info['description']}")
        return
    
    # 显示访问地址
    if args.urls:
        manager.print_access_urls()
        return
    
    # 健康检查
    if args.health:
        results = manager.health_check(args.service)
        
        # 输出JSON格式结果
        print(f"\n📄 健康检查结果 (JSON):")
        print(json.dumps(results, indent=2, ensure_ascii=False))
        return
    
    # 查看状态
    if args.status:
        manager.print_service_status()
        return
    
    # 启动服务
    if args.service:
        # 启动指定服务
        if args.service not in manager.services:
            print(f"❌ 未知服务: {args.service}")
            print(f"可用服务: {', '.join(manager.services.keys())}")
            return
        
        print(f"🚀 启动服务: {args.service}")
        process = manager.start_service(args.service)
        
        if process:
            manager.print_service_status()
            manager.wait_for_services()
    else:
        # 启动所有服务
        manager.start_all_services()
        # 默认不自动打印访问地址，减少噪音；需要时可加 --urls
        manager.wait_for_services()


if __name__ == "__main__":
    main()
